#include "stdafx.h"
#include "problem_solver_core.h"
#include "problem.h"
#include "solver.h"
#include "Solver Form.h"
#include "Input.h"
#include "Output.h"
#include "Target.h"

namespace nnse
{
extern io_module io_m;
}

namespace SimpleGUI
{
	// Constructor and Destructor

	template <class T, class U> Solver<T, U>::Solver(nnse::solver<T, U>^ p)
	: parent(p)
	{
		InitializeComponent();
		load_toolTip->SetToolTip(load_button, "Load a previously saved Solver from a file.");
		save_toolTip->SetToolTip(save_button, "Save the current Solver to a file.");
		train_toolTip->SetToolTip(train_button, "Train the Neural Network with each of the training examples in the currently loaded set.");
		test_toolTip->SetToolTip(test_button, "Test the Neural Network with each of the testing examples in the currently loaded set.");
		prev_toolTip->SetToolTip(prev_button, "Test the Neural Network with the previous testing example in the set.");
		next_toolTip->SetToolTip(next_button, "Test the Neural Network with the next testing example in the set.");
		title_textBox->Enabled=false;
		number_of_training_examples_textBox->Enabled=false;
		number_of_testing_examples_textBox->Enabled=false;
		current_training_example_textBox->Enabled=false;
		current_testing_example_textBox->Enabled=false;
		update_form("Ready", 0, 0, 0);
		this->Show();
	};

	template <class T, class U> Solver<T, U>::~Solver()
	{
		if (components)
		{
			delete components;
		}
	};

	// GUI Functions

	template <class T, class U> System::Void Solver<T, U>::load_button_Click(System::Object^  sender, System::EventArgs^  e)
	{
		try
		{
			if (load_openFileDialog->ShowDialog()==System::Windows::Forms::DialogResult::OK)
			{
				update_form("Loading...", 0, 0, 0);
				parent->load(load_openFileDialog->FileName);
				update_form("Ready", 0, 0, 0);
			}
		}
		catch(const std::exception& error)
		{
			nnse::io_m.cerr_stream << error.what() << std::endl;
		}
	};

	template <class T, class U> System::Void Solver<T, U>::save_button_Click(System::Object^  sender, System::EventArgs^  e)
	{
		try
		{
			if (save_saveFileDialog->ShowDialog()==System::Windows::Forms::DialogResult::OK)
			{
				update_form("Saving...", 0, 0, 0);
				parent->save(save_saveFileDialog->FileName);
				update_form("Ready", 0, 0, 0);
			}
		}
		catch(const std::exception& error)
		{
			nnse::io_m.cerr_stream << error.what() << std::endl;
		}
	};

	template <class T, class U> System::Void Solver<T, U>::train_button_Click(System::Object^  sender, System::EventArgs^  e)
	{
		try
		{
			update_form("Training in progress...", 0, 0, 0);
			parent->training(0);
			update_form("Ready", 0, 0, 0);
		}
		catch(const std::exception& error)
		{
			nnse::io_m.cerr_stream << error.what() << std::endl;
		}
	};

	template <class T, class U> System::Void Solver<T, U>::test_button_Click(System::Object^  sender, System::EventArgs^  e)
	{
		try
		{
			update_form("Testing in progress...", 0, 0, 0);
			parent->testing(0);
			update_form("Ready", 0, 0, 0);
		}
		catch(const std::exception& error)
		{
			nnse::io_m.cerr_stream << error.what() << std::endl;
		}
	};

	template <class T, class U> System::Void Solver<T, U>::prev_button_Click(System::Object^ sender, System::EventArgs^ e)
	{
		update_form("Getting previous example...", 0, 0, 0);
		unsigned int current_example=parent->get_parent_problem()->get_current_example();
		if (current_example==0)
		{
			parent->get_parent_problem()->put_current_example(parent->get_parent_problem()->get_number_of_examples()-1);
		}
		else
		{
			parent->get_parent_problem()->put_current_example(current_example-1);
		}
		parent->show_vectors();
		update_form("Ready", 0, 0, 0);
	};

	template <class T, class U> System::Void Solver<T, U>::next_button_Click(System::Object^ sender, System::EventArgs^ e)
	{
		update_form("Getting next example...", 0, 0, 0);
		unsigned int current_example=parent->get_parent_problem()->get_current_example();
		if (current_example==parent->get_parent_problem()->get_number_of_examples()-1)
		{
			parent->get_parent_problem()->put_current_example(0);
		}
		else
		{
			parent->get_parent_problem()->put_current_example(current_example+1);
		}
		parent->show_vectors();
		update_form("Ready", 0, 0, 0);
	};

	template <class T, class U> System::Void Solver<T, U>::input_button_Click(System::Object^  sender, System::EventArgs^  e)
	{
		parent->display_input_form();
	};

	template <class T, class U> System::Void Solver<T, U>::output_button_Click(System::Object^  sender, System::EventArgs^  e)
	{
		parent->display_output_form();
	};

	template <class T, class U> System::Void Solver<T, U>::target_button_Click(System::Object^  sender, System::EventArgs^  e)
	{
		parent->display_target_form();
	};

	template <class T, class U> System::Void Solver<T, U>::view_button_Click(System::Object^  sender, System::EventArgs^  e)
	{
		parent->display_MLPs();
	};

	template <class T, class U> System::Void Solver<T, U>::form_closed(System::Object^  sender, System::Windows::Forms::FormClosedEventArgs^  e)
	{
		parent->invalidate_solver_form();
	};

	template <class T, class U> System::Void Solver<T, U>::update_form(System::String^ progress_text, unsigned int progress_min, unsigned int progress_val, unsigned int progress_max)
	{
		title_textBox->Text=parent->get_title();
		number_of_training_examples_textBox->Text=parent->get_parent_problem()->get_number_of_training_examples().ToString();
		number_of_testing_examples_textBox->Text=parent->get_parent_problem()->get_number_of_testing_examples().ToString();
		current_training_example_textBox->Text=(parent->get_parent_problem()->get_current_training_example() + 1).ToString();
		current_testing_example_textBox->Text=(parent->get_parent_problem()->get_current_testing_example() + 1).ToString();
		number_of_MLPs_textBox->Text=parent->get_number_of_MLPs().ToString();
		status_label->Text=progress_text;
		status_progressBar->Minimum=progress_min;
		status_progressBar->Value=progress_val;
		status_progressBar->Maximum=progress_max;
		this->Refresh();
	}

	// Explicit Instantiation

	template ref class Solver<bool, double>;
	template ref class Solver<unsigned char, double>;
}
